package org.infosys.basic.service.impl;

import org.infosys.basic.constant.BaseConstants;
import org.infosys.basic.exception.BusinessException;
import org.infosys.basic.service.IVerifyCodeService;
import org.infosys.basic.utils.StrUtils;
import org.infosys.basic.utils.VerifyCodeUtils;
import org.infosys.basic.vo.RegisterVo;
import org.infosys.user.domain.User;
import org.infosys.user.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.util.concurrent.TimeUnit;

@Service
public class VerifyCodeServiceImpl implements IVerifyCodeService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private UserMapper userMapper;

    /**
    * @Title: getImageCode
    * @Description: 生成图形验证码
    * @Author: hank
    * @Version: 1.0
    * @Date:  2022/7/6 15:32
    * @Parameters: [key]
    * @Return java.lang.String
    */
    @Override
    public String getImageCode(String key) {
        if (StringUtils.isEmpty(key)) {
            throw new BusinessException("请传递必要参数！");
        }
        // 生成随机四个字符串
        String code = StrUtils.getComplexRandomString(4);
        // 将生产的字符串存入redis中
        redisTemplate.opsForValue().set(key, code, 5, TimeUnit.MINUTES);
        // 将code生成图形并编码成Base64
        String base64Str = VerifyCodeUtils.VerifyCode(100, 35, code);

        return base64Str;
    }

    /**
    * @Title: smsCode
    * @Description: 发送手机验证码
    * @Author: hank
    * @Version: 1.0
    * @Date:  2022/7/6 15:33
    * @Parameters: [registerVo]
    * @Return void
    */
    @Override
    public void smsCode(RegisterVo registerVo) {

        String phone = registerVo.getPhone();
        String type = registerVo.getType();

        // 判断参数非空
        if (StringUtils.isEmpty(phone)) {
            throw new BusinessException("请输入电话号码");
        }
        if (StringUtils.isEmpty(type)) {
            throw new BusinessException("参数错误");
        }
        // 判断是注册还是微信登录时绑定账号
        if ("register".equals(type)) {
            // 注册时，判断图形验证码是否有问题
            isImageCode(registerVo);
            // 使用业务键拼接手机号
            String phoneCodeKey = BaseConstants.VerifyCodeConstant.BUSINESS_REGISTER_KEY + phone;
            // 直接调用发送短信验证码的方法
            sendSmsCode(phoneCodeKey);
        } else if("binder".equals(type)) {
            // type等于binder那么就直接发送短信验证码
            String phoneCodeKey = BaseConstants.VerifyCodeConstant.BUSINESS_BINDER_KEY + phone;
            sendSmsCode(phoneCodeKey);
        } else {
            throw new BusinessException("参数错误！");
        }

    }

    /**
    * @Title: isImageCode
    * @Description: 校验图形验证码
    * @Author: hank
    * @Version: 1.0
    * @Date:  2022/7/10 19:37
    * @Parameters: [registerVo]
    * @Return void
    */
    public void isImageCode(RegisterVo registerVo) {
        String imageCodeKey = registerVo.getImageCodeKey();
        String imageCodeValue = registerVo.getImageCodeValue();
        if (StringUtils.isEmpty(imageCodeKey)) {
            throw new BusinessException("参数不正确");
        }
        if (StringUtils.isEmpty(imageCodeValue)) {
            throw new BusinessException("请输入图形验证码");
        }
        // 根据传入的imageCodeKey查询redis中是否存在这个零时的图形验证码
        Object imageCode = redisTemplate.opsForValue().get(imageCodeKey);
        // 为空,抛出异常
        if (ObjectUtils.isEmpty(imageCode)) {
            throw new BusinessException("图形验证码过期了，请重试");
        }
        // 不一致抛出异常
        if (!imageCode.toString().equalsIgnoreCase(imageCodeValue)) {
            throw new BusinessException("图形验证码不正确");
        }
        // 判断用户是否已经注册过
        User user = userMapper.loadByPhone(registerVo.getPhone());
        if (!ObjectUtils.isEmpty(user)) {
            throw new BusinessException("该号码已注册，请直接登录！");
        }

    }

    /**
    * @Title: sendSmsCode
    * @Description: 发送手机验证码
    * @Author: hank
    * @Version: 1.0
    * @Date:  2022/7/10 19:42
    * @Parameters: [smsCodeKey]
    * @Return void
    */
    public void sendSmsCode(String phoneCodeKey) {
        Object phoneCodeValue = redisTemplate.opsForValue().get(phoneCodeKey);
        String phoneCode = "";
        if (ObjectUtils.isEmpty(phoneCodeValue)) {
            // 不存在，需要生成新的随机验证码
            phoneCode = StrUtils.getComplexRandomString(4);
        } else {
            // 存在，获取redis中原来的value并分割，小于1分钟，抛出异常，
            String[] phoneCodeValueTemp = phoneCodeValue.toString().split(":");
            long differenceTime = System.currentTimeMillis() - Long.valueOf(phoneCodeValueTemp[0]);
            if (differenceTime < 1*60*1000) {
                throw new BusinessException("请一分钟之后再获取");
            }
            // 将旧的验证码赋值给phoneCode
            phoneCode = phoneCodeValueTemp[1];
        }
        // 通过业务键+phone作为key,验证码+时间戳作为value，存入redis,并设置为三分钟有效
        String phoneCodeValueRedis = System.currentTimeMillis() + ":" + phoneCode;
        redisTemplate.opsForValue().set(phoneCodeKey, phoneCodeValueRedis, 3, TimeUnit.MINUTES);
        // 发送短信验证码
        // SmsUtils.sendCode(phone, "亲，您的验证码是："+ phoneCode);
        System.out.println("亲，您的验证码是："+ phoneCode);
    }
}
